#include "pch.h"
#include "DLKit.h"

#pragma comment(lib, "./third_party/openvino/lib/intel64/Release/openvino.lib")
#pragma comment(lib, "./third_party/openvino/lib/intel64/Release//openvino_onnx_frontend.lib")
#pragma comment(lib,"./third_party/opencv4120/opencv_world4120.lib")


#pragma warning (disable:4244)

cv::Mat DLKit::formatToSquare(const cv::Mat& img, std::vector<double>& paddings, std::vector<int> new_shape)
{
	auto img_h = img.rows;
	auto img_w = img.cols;
	// compute scale ratio
	auto scale = std::min(new_shape[1] * 1.0 / img_h, new_shape[0] * 1.0 / img_w);
	auto resize_h = int(round(img_h * scale));
	auto resize_w = int(round(img_w * scale));
	paddings[0] = scale;

	// compute padding
	int pad_h = new_shape[1] - resize_h;
	int pad_w = new_shape[0] - resize_w;
	cv::Mat resized_img;
	cv::resize(img, resized_img, cv::Size(resize_w, resize_h));

	// divide padding into 2 sides
	auto half_h = pad_h * 1.0 / 2.0;
	auto half_w = pad_w * 1.0 / 2.0;
	paddings[1] = half_h; // 
	paddings[2] = half_w; // 

	// compute padding border
	int top = int(round(half_h - 0.1));
	int bottom = int(round(half_h + 0.1));
	int left = int(round(half_w - 0.1));
	int right = int(round(half_w + 0.1));

	// add border
	cv::copyMakeBorder(resized_img, resized_img, top, bottom, left, right, 0, cv::Scalar(114, 114, 114));
	return resized_img;
}

double DLKit::RGBToCCT(int R, int G, int B)
{
	double trimX = 2.789 * R + 1.7517 * G + 1.1302 * B;
	double trimY = 1 * R + 4.5907 * G + 0.0601 * B;
	double trimZ = 0 * R + 0.0565 * G + 5.5943 * B;
	double coorX = trimX / (trimX + trimY + trimZ);
	double coorY = trimY / (trimX + trimY + trimZ);
	double n = (coorX - 0.3320) / (0.1858 - coorY);
	double CCT = 437 * n * n * n + 3601 * n * n + 6831 * n + 5517;
	return CCT;
}


void DLKit::CCTToRGB(int kelvin, int* r, int* g, int* b) {
    double tmpCalc = 0;
    auto tmpKelvin = kelvin;
    if (tmpKelvin < 1000)
    {
        tmpKelvin = 1000;
    }

    if (tmpKelvin > 40000)
    {
        tmpKelvin = 40000;
    }

    tmpKelvin = tmpKelvin / 100;

    /*----#red----------------------------------------------------------------------------*/
    if (tmpKelvin <= 66)
    {
        *r = 255;
    }
    else
    {
        tmpCalc = tmpKelvin - 60;
        tmpCalc = 329.698727446 * (pow(tmpCalc, -0.1332047592));
        *r = tmpCalc;
        if (*r < 0)
        {
            *r = 0;
        }

        if (*r > 255)
        {
            *r = 255;
        }

    }

    /*----#green----------------------------------------------------------------------------*/
    if (tmpKelvin <= 66)
    {
        tmpCalc = tmpKelvin;
        tmpCalc = 99.4708025861 * log(tmpCalc) - 161.1195681661;
        *g = tmpCalc;

        if (*g < 0)
        {
            *g = 0;
        }

        if (*g > 255)
        {
            *g = 255;
        }

    }
    else
    {
        tmpCalc = tmpKelvin - 60;
        tmpCalc = 288.1221695283 * (pow(tmpCalc, -0.0755148492));
        *g = tmpCalc;

        if (*g < 0)
        {
            *g = 0;
        }

        if (*g > 255)
        {
            *g = 255;
        }


    }

    /*----#blue----------------------------------------------------------------------------*/

    if (tmpKelvin >= 66)
    {
        *b = 255;
    }
    else if (tmpKelvin <= 19)
    {
        *b = 0;
    }
    else
    {
        tmpCalc = tmpKelvin - 10;
        tmpCalc = 138.5177312231 * log(tmpCalc) - 305.0447927307;
        *b = tmpCalc;

        if (*b < 0)
        {
            *b = 0;
        }

        if (*b > 255)
        {
            *b = 255;
        }
    }

}



float DLKit::OverlapArea(cv::Rect2f A, cv::Rect2f B) {
	int x1 = (int)std::max(A.x, B.x);
	int y1 = (int)std::max(A.y, B.y);
	int x2 = (int)std::min(A.x + A.width, B.x + B.width);
	int y2 = (int)std::min(A.y + A.height, B.y + B.height);
	int width = x2 - x1;
	int height = y2 - y1;
	if (width < 0 || height < 0) return 0;
	return width * height;
}

int DLKit::OverlapArea(cv::Rect A, cv::Rect B) {
	int x1 = (int)std::max(A.x, B.x);
	int y1 = (int)std::max(A.y, B.y);
	int x2 = (int)std::min(A.x + A.width, B.x + B.width);
	int y2 = (int)std::min(A.y + A.height, B.y + B.height);
	int width = x2 - x1;
	int height = y2 - y1;
	if (width < 0 || height < 0) return 0;
	return width * height;
}

float DLKit::OverlapAreaRatio(cv::Rect A, cv::Rect B)
{
	auto AreaOfROI = B.width * B.height;
	auto OverLapAreaValue = OverlapArea(A, B);
	auto Area = A.width * A.height;
	Area = Area < AreaOfROI ? Area : AreaOfROI;
	return ((float)(OverLapAreaValue) / Area);
}

void DLKit::crop_image(cv::Mat& InputArray, cv::Mat* OutPutArray, float Row1, float Col1, float Row2, float Col2)
{
	(void)InputArray;
	(void)OutPutArray;
	(void)Row1;
	(void)Row2;
	(void)Col1;
	(void)Col2;
}

//功能是 将cv::Rect 这种格式 转换成中心点x,y,w,h的格式 
void DLKit::xywh2cxywh(const xydata xywh, xydata& cxywh, int imageWidth, int imageHeight)
{
	if(imageHeight==0 || imageWidth==0)
	{
		return;
	}
	cxywh.x = (xywh.x + xywh.w / 2.0) / imageWidth;
	cxywh.y = (xywh.y + xywh.h / 2.0) / imageHeight;
	cxywh.w = xywh.w * 1.0 / imageWidth;
	cxywh.h = xywh.h * 1.0 / imageHeight;
}



#if 0
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

/*
 */
typedef struct Bbox
{
	int x1;
	int y1;
	int x2;
	int y2;
	float score;
}Bbox;

/*
  ����iou
 */
float iou(Bbox box1, Bbox box2)
{
	max_x = max(box1.x1, box2.x1);  // �ҳ����Ͻ������ĸ���
	min_x = min(box1.x2, box2.x2);  // �ҳ����Ͻ������ĸ�С
	max_y = max(box1.y1, box2.y1);
	min_y = min(box1.y2, box2.y2);
	if (min_x <= max_x || min_y <= max_y) // ���û���ص�
		return 0;
	float over_area = (min_x - max_x) * (min_y - max_y);  // �����ص����
	float area_a = (box1.x2 - boxa.x1) * (box1.y2 - boxa.y1);
	float area_b = (box2.x2 - boxb.x1) * (box2.y2 - boxb.y1);
	float iou = over_area / (area_a + area_b - over_area);
	return iou;
}

/*
*/
bool sort_score(Bbox box1, Bbox box2)
{
	return (box1.score > box2.score);
}
/*
*/
vector<Bbox> nms(vector<Bbox>& vec_boxs, float threshold)
{
	vector<Bbox>  res;
	while (vec_boxs.size() > 0)
	{
		sort(vec_boxs.begin(), vec_boxs.end(), cmp);
		res.push_back(vec_boxs[0]);
		for (int i = 0; i < vec_boxs.size() - 1; i++)
		{
			float iou_value = iou(vec_boxs[0], vec_boxs[i + 1]);
			if (iou_value > threshold)
			{
				vec_boxs.erase(vec_boxs[i + 1]);
			}
		}
		vec_boxs.erase(vec_boxs[0]);  // res �Ѿ����棬���Կ��Խ�����ɾ����

	}
	return res;
}
#endif